//============================================================================
// Name        : coreinfo.cpp
// Author      : Onega Zhang
// Version     : 12/21/2013
// Copyright   : Your copyright notice
// Description : utility to analyze core dump file via gdb
//============================================================================
#define wxUSE_UNICODE 1
#define __WXGTK__
#define _FILE_OFFSET_BITS 64
#include <wx/wx.h>
#include <sstream>
#include <wx/clipbrd.h>
#include <wx/gbsizer.h>
	extern char _binary_gdbcmd_txt_start, _binary_gdbcmd_txt_size;
//	extern char _binary_gdbcmd_txt_end; // unused symbol

wxString exec_cmd(const char* cmdstr) {
	char buffer[1024];
	FILE *stream = popen(cmdstr, "r");
	wxString sret;
	if (stream) {
		wxLogVerbose("start %s \n", cmdstr);
		while (!feof(stream)) {
			if (fgets(buffer, sizeof(buffer)-1, stream) != NULL) {
				sret.Append(buffer);
			}
		}
		pclose(stream);
		wxLogVerbose("end %s \n", cmdstr);
	} else
		sret.Printf("ERROR popen %s\n", cmdstr);
	return sret;
}

class MyAboutDlg : public wxDialog {
public:
	MyAboutDlg(wxWindow* parent);
private:
	wxTextCtrl* main;
	char cmdbuf[256];
};
MyAboutDlg::MyAboutDlg(wxWindow* parent):wxDialog(parent, wxID_ANY,
		wxT("(Onega) libraries of coreinfo"), wxDefaultPosition,
		wxSize(600, 480), wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
{
	wxGridBagSizer *gbsizer=new wxGridBagSizer();
	main = new wxTextCtrl(this, wxID_ANY,
			wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxHSCROLL);
	main->SetWindowStyle(main->GetWindowStyle() & ~wxTE_DONTWRAP | wxTE_BESTWRAP);
	gbsizer->Add(main, wxGBPosition(0,0), wxDefaultSpan, wxGROW);
	gbsizer->AddGrowableRow(0);
	gbsizer->AddGrowableCol(0);
	SetSizer(gbsizer);
	sprintf(cmdbuf, "grep so /proc/%d/maps |awk '{print $6}' | uniq | sort", getpid());
	main->SetValue(exec_cmd(cmdbuf));
}

class MiniWxApp: public wxApp {
	virtual bool OnInit();
};
IMPLEMENT_APP (MiniWxApp)
class MyFrame: public wxFrame {
public:
	MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size);
	void OnQuit(wxCommandEvent& event) {
		Close(true);
	}
	void OnAbout(wxCommandEvent& event);
	void OnEraseBackground(wxEraseEvent& event) {
		wxClientDC dc(this);
		dc.Clear();
	}
	void OnPaint(wxPaintEvent& evt) {
		wxClientDC dc(this);
		wxDateTime dt = wxDateTime::Now();
		wxString txt;
		txt.Printf(wxT("pid:%d "), getpid());
		txt.Append(dt.FormatTime());
		dc.SetTextForeground(*wxBLUE);
		dc.SetBackgroundMode(wxTRANSPARENT);
		dc.DrawText(txt, 0, 0);
	}
	void OnCopyClick(wxCommandEvent&)
	{
		wxString gdbname, exepath, corepath;
		gdbname = m_gdb->GetValue();
		exepath = m_img->GetValue();
		corepath = m_corefile->GetValue();
		if (gdbname.length()>0 && corepath.length()>0 && exepath.length()==0)
			return FindExectuable(corepath);
		if (gdbname.length() > 0 && corepath.length() > 0
				&& exepath.length() > 0) {
			wxString txtfile(&_binary_gdbcmd_txt_start,
					(int) &_binary_gdbcmd_txt_size);
			wxString cmdpattern;
			cmdpattern.Printf(txtfile, gdbname, exepath, corepath);
			m_coreinfo->SetValue(cmdpattern);
			m_coreinfo->SetValue(exec_cmd(cmdpattern.c_str()));
		}
//		cmdpattern.Printf(m_coreinfo->GetValue(), )
//		wxClipboard cb;
//		if(cb.Open()){
//			cb.Clear();
//		cb.SetData(new wxTextDataObject(m_coreinfo->GetValue()));
//		cb.Flush();
//		cb.Close();
//		}
	}
	void FindExectuable(wxString corefile)
	{
		wxString cmdstr;
		cmdstr.Printf(wxT("%s -core \"%s\" -ex quit | grep \"Core was generated by\""),
				m_gdb->GetValue().c_str(), m_corefile->GetValue().c_str());
		wxLogDebug(wxT("%s"), cmdstr);
		m_coreinfo->SetValue(exec_cmd(cmdstr.c_str()));
	}
	wxString ChooseFile(wxString currentexe, wxString title,
			wxString filenamepattern) {
		wxString defaultpath = wxEmptyString;
		wxString selectedfile;
		if (currentexe.length()) {
			size_t pos = currentexe.rfind(wxT("/"));
			if (pos != wxString::npos)
				defaultpath = currentexe.substr(0, pos);
		}
		wxFileDialog* OpenDialog = new wxFileDialog(this, title, defaultpath,
				wxEmptyString, filenamepattern, wxFD_OPEN, wxDefaultPosition);
		if (OpenDialog->ShowModal() == wxID_OK)
			selectedfile = OpenDialog->GetPath();
		OpenDialog->Destroy();
		return selectedfile;
	}
	void OnSelectExecutable(wxCommandEvent&)
	{
		m_img->SetValue(ChooseFile(m_img->GetValue(), wxT("Choose executable file"),
				wxT("executable file (*)|*")));
	}
	void OnSelectCoreFile(wxCommandEvent&)
	{
		m_corefile->SetValue(ChooseFile(m_corefile->GetValue(),
				wxT("Choose core dump file"),
				wxT("core dump file (core*)|core*|all files|*")));
	}
	void OnReset(wxCommandEvent&)
	{
		reset();
	}
private:
	void reset()
	{
		m_gdb->SetValue(wxT("arm-marvell-linux-gnueabi-gdb"));
		m_corefile->SetValue(wxEmptyString);
		m_img->SetValue(wxEmptyString);
		wxString txtfile(&_binary_gdbcmd_txt_start, (int)&_binary_gdbcmd_txt_size);
			m_coreinfo->SetValue(txtfile);
	}
	void InitButtons();
	wxString libs;
	wxTextCtrl *m_img;
	wxTextCtrl *m_corefile;
	wxTextCtrl *m_coreinfo;
	wxTextCtrl *m_gdb;
	wxButton *m_select_img;
	wxButton *m_select_corefile;
	wxButton *m_copy;
	wxButton *m_reset;
};

bool MiniWxApp::OnInit() {
	wxString title;
	title.Printf(wxT("Onega’s mini wxWidgets application pid:%d "), getpid());
	MyFrame *frame = new MyFrame( title, wxDefaultPosition, wxDefaultSize);
	frame->Show(true);
	SetTopWindow (frame);
	return true;
}

void MyFrame::InitButtons() {
	m_copy = new wxButton(this, wxID_ANY, wxT("Process"), wxDefaultPosition,
			wxDefaultSize, 0);
	m_select_img = new wxButton(this, wxID_ANY, wxT("Executable..."),
			wxDefaultPosition, wxDefaultSize, 0);
	m_select_corefile = new wxButton(this, wxID_ANY, wxT("Core dump..."),
			wxDefaultPosition, wxDefaultSize, 0);
	m_reset = new wxButton(this, wxID_ANY, wxT("Clear"), wxDefaultPosition,
			wxDefaultSize, 0);
	m_copy->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
			wxCommandEventHandler(MyFrame::OnCopyClick), NULL, this);
	m_select_img->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
			wxCommandEventHandler(MyFrame::OnSelectExecutable), NULL, this);
	m_select_corefile->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
			wxCommandEventHandler(MyFrame::OnSelectCoreFile), NULL, this);
	m_reset->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
			wxCommandEventHandler(MyFrame::OnReset), NULL, this);
}

MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size) :
		wxFrame(NULL, -1, title, pos, size) {
	wxMenuBar *menuBar = new wxMenuBar;
	wxMenu *menuFile = new wxMenu;
	menuFile->Append(wxID_ABOUT, wxT("&About…"));
	menuFile->Append(wxID_EXIT, wxT("E & xit"));
	menuBar->Append(menuFile, wxT("&File"));
	SetMenuBar(menuBar);

	InitButtons();
	m_gdb = new wxTextCtrl(this, wxID_ANY);
	m_img = new wxTextCtrl(this, wxID_ANY);
	m_corefile = new wxTextCtrl(this, wxID_ANY);
	m_coreinfo = new wxTextCtrl(this, wxID_ANY,
			wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxHSCROLL);
	m_coreinfo->SetWindowStyle(m_coreinfo->GetWindowStyle() & ~wxTE_DONTWRAP | wxTE_BESTWRAP);

	wxGridBagSizer *m_fgsizer = new wxGridBagSizer;
	int row = 0;
	m_fgsizer->Add(new wxStaticText(this, wxID_ANY, wxEmptyString), wxGBPosition(row,0));
	m_fgsizer->Add(m_gdb, wxGBPosition(row,1), wxDefaultSpan, wxGROW);
	row++;
	m_fgsizer->Add(m_select_img, wxGBPosition(row,0));
	m_fgsizer->Add(m_img, wxGBPosition(row,1), wxDefaultSpan, wxGROW);
	row++;
	m_fgsizer->Add(m_select_corefile, wxGBPosition(row,0));
	m_fgsizer->Add(m_corefile, wxGBPosition(row,1), wxDefaultSpan, wxGROW);
	row++;
	m_fgsizer->Add(m_copy, wxGBPosition(row,0));
	m_fgsizer->Add(m_coreinfo, wxGBPosition(row,1), wxGBSpan(3,1), wxGROW);
	row++;
	m_fgsizer->Add(m_reset, wxGBPosition(row,0));
	m_fgsizer->AddGrowableCol(1);
	m_fgsizer->AddGrowableRow(row);
	this->SetSizer(m_fgsizer);

	Connect(wxID_EXIT, wxEVT_COMMAND_MENU_SELECTED,
			(wxObjectEventFunction) & MyFrame::OnQuit);
	Connect(wxID_ABOUT, wxEVT_COMMAND_MENU_SELECTED,
			(wxObjectEventFunction) & MyFrame::OnAbout);
	Connect(wxEVT_PAINT, wxPaintEventHandler(MyFrame::OnPaint));
	Connect(wxEVT_ERASE_BACKGROUND,
			wxEraseEventHandler(MyFrame::OnEraseBackground));
	char cmdbuf[1024];
	      sprintf(cmdbuf, "grep so /proc/%d/maps |awk '{print $6}' | uniq", getpid());
	libs = (exec_cmd(cmdbuf));
	reset();
}

void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event)) {
	MyAboutDlg dlg(this);
	dlg.ShowModal();
	return;
	wxString caption = wxT("Onega’s mini wxWidgets application @ 12/21/2013.");
//	wxString body;
//	body.Append(caption);
//	body.Append(wxT("\n"));
//	body.Append(wxT("cl / EHsc / MD - DUNICODE = 1 "));
//	wxT(“-ID:\\src\\wxWidgets-2.9.1\\include “)
//	wxT(“-ID:\\src\\wxWidgets-2.9.1\\lib\\vc_libvc90\\mswu miniwx.cpp “)
//	wxT(“/link -LIBPATH:D:\\src\\wxWidgets-2.9.1\\lib\\vc_libvc90 “)
//	wxT(“gdi32.lib rpcrt4.lib user32.lib Comdlg32.lib comctl32.lib “)
//	wxT(“ole32.lib oleaut32.lib Advapi32.lib shell32.lib Winspool.lib wxmsw29u.lib”);
//	wxMessageBox(body, caption, wxOK | wxICON_INFORMATION, this);
}
// /home2/onega/oss/wxWidgets-3.0.0/wx-config --cppflags
//  /home2/onega/oss/wxWidgets-3.0.0/wx-config --libs
// '-Wl,-rpath,/home2/onega/oss/wxWidgets-3.0.0/lib'
// -rpath /home2/onega/oss/wxWidgets-3.0.0/lib
/*
make pre-build main-build
Build gdbcmds.txt
cd /home2/onega/workspace/cdt/coreinfo/src && objcopy --input binary --output elf32-i386 --binary-architecture i386 gdbcmd.txt /home2/onega/workspace/cdt/coreinfo/Debug/gdbcmds.o;objcopy --input binary --output elf32-i386 --binary-architecture i386 coreinfo.cpp /home2/onega/workspace/cdt/coreinfo/Debug/mysrc.o

Building file: ../src/coreinfo.cpp
Invoking: GCC C++ Compiler
g++ -I/home2/onega/oss/wxWidgets-3.0.0/include -I/home2/onega/oss/wxWidgets-3.0.0/lib/wx/include/gtk2-unicode-3.0 -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"src/coreinfo.d" -MT"src/coreinfo.d" -o "src/coreinfo.o" "../src/coreinfo.cpp"

Building target: coreinfo
Invoking: GCC C++ Linker
g++ -L/home2/onega/oss/wxWidgets-3.0.0/lib -L"/home2/onega/workspace/cdt/coreinfo/Debug" -Wl,-rpath,/home2/onega/oss/wxWidgets-3.0.0/lib -o "coreinfo"  ./src/coreinfo.o  gdbcmds.o mysrc.o -lwx_baseu-3.0 -lwx_gtk2u_core-3.0
Finished building target: coreinfo
*/
